package com.neusoft.hifly.core.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * 线程池
 * <p>
 * 使用@Async不好用的问题：
 * <p>
 * 1、加入@Async注解的方法，不能在被调用的类中
 * <p>
 * 2、注意添加@EnableAsync注解
 */
@Configuration
@Component
@EnableAsync
public class ThreadPoolConfig implements AsyncConfigurer {
	//	# 异步线程配置
	//	# 配置核心线程数
	//	async.executor.thread.core_pool_size: 5
	//	# 配置最大线程数
	//	async.executor.thread.max_pool_size: 10
	//	# 配置队列大小
	//	async.executor.thread.queue_capacity: 99999
	//	# 设置线程活跃时间（秒）
	//	async.executor.thread.keep_alive_seconds: 60
	//	# 配置线程池中的线程的名称前缀
	//	async.executor.thread.name_prefix: ctcloud-micro-
	//	# 线程池的拒绝策略（CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy）
	//	async.executor.thread.rejecte_dexecution_handler: CallerRunsPolicy

	@Value("${async.executor.thread.core_pool_size:5}")
	private int corePoolSize;

	@Value("${async.executor.thread.max_pool_size:10}")
	private int maxPoolSize;

	@Value("${async.executor.thread.queue_capacity:99999}")
	private int queueCapacity;

	@Value("${async.executor.thread.keep_alive_seconds:60}")
	private int keepAliveSeconds;

	@Value("${async.executor.thread.name_prefix:hifly-micro-}")
	private String threadNamePrefix;

	@Value("${async.executor.thread.rejecte_dexecution_handler:CallerRunsPolicy}")
	private String rejectedExecutionHandler;

	@Override
	public Executor getAsyncExecutor() {
		final ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		// 配置核心线程数
		taskExecutor.setCorePoolSize(getCorePoolSize());
		// 配置最大线程数
		taskExecutor.setMaxPoolSize(getMaxPoolSize());
		// 配置队列大小
		taskExecutor.setQueueCapacity(getQueueCapacity());
		// 设置线程活跃时间（秒）
		taskExecutor.setKeepAliveSeconds(getKeepAliveSeconds());
		// 配置线程池中的线程的名称前缀
		taskExecutor.setThreadNamePrefix(getThreadNamePrefix());
		// 线程池的拒绝策略
		//	CallerRunsPolicy - 当触发拒绝策略，只要线程池没有关闭的话，则使用调用线程直接运行任务。一般并发比较小，性能要求不高，不允许失败。但是，由于调用者自己运行任务，如果任务提交速度过快，可能导致程序阻塞，性能效率上必然的损失较大
		//	AbortPolicy - 丢弃任务，并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常，否则会打断当前的执行流程，影响后续的任务执行。
		//	DiscardPolicy - 直接丢弃，其他啥都没有
		//	DiscardOldestPolicy - 当触发拒绝策略，只要线程池没有关闭的话，丢弃阻塞队列 workQueue 中最老的一个任务，并将新任务加入
		if ("CallerRunsPolicy".equalsIgnoreCase(getRejectedExecutionHandler())) {
			taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		} else if ("AbortPolicy".equalsIgnoreCase(getRejectedExecutionHandler())) {
			taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
		} else if ("DiscardPolicy".equalsIgnoreCase(getRejectedExecutionHandler())) {
			taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
		} else if ("DiscardOldestPolicy".equalsIgnoreCase(getRejectedExecutionHandler())) {
			taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
		}
		// 执行初始化
		taskExecutor.initialize();
		return taskExecutor;
	}

	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return null;
	}

	public int getCorePoolSize() {
		return corePoolSize;
	}

	public void setCorePoolSize(final int corePoolSize) {
		this.corePoolSize = corePoolSize;
	}

	public int getMaxPoolSize() {
		return maxPoolSize;
	}

	public void setMaxPoolSize(final int maxPoolSize) {
		this.maxPoolSize = maxPoolSize;
	}

	public int getQueueCapacity() {
		return queueCapacity;
	}

	public void setQueueCapacity(final int queueCapacity) {
		this.queueCapacity = queueCapacity;
	}

	public int getKeepAliveSeconds() {
		return keepAliveSeconds;
	}

	public void setKeepAliveSeconds(final int keepAliveSeconds) {
		this.keepAliveSeconds = keepAliveSeconds;
	}

	public String getThreadNamePrefix() {
		return threadNamePrefix;
	}

	public void setThreadNamePrefix(final String threadNamePrefix) {
		this.threadNamePrefix = threadNamePrefix;
	}

	public String getRejectedExecutionHandler() {
		return rejectedExecutionHandler;
	}

	public void setRejectedExecutionHandler(final String rejectedExecutionHandler) {
		this.rejectedExecutionHandler = rejectedExecutionHandler;
	}

}